#include "MyTask.h"
#include "Mydict.h"
#include <stdlib.h>
#include <unistd.h>
#include <iostream>

MyTask::MyTask(const string& queryWord,const xkk::TcpConnectionPtr &conn)
:_queryWord(queryWord)
    ,_conn(conn)
    ,_resultQue()
{}

/* void MyTask::execute(Cache& cache){} */

void MyTask::queryIndexTable()
{
    int flag=1;
    string word=getFirstWord();
    if(Mydict::createInstance()->getIndexTable().find(word)==
       Mydict::createInstance()->getIndexTable().end()){
        flag=0;
        _conn->sendInLoop(to_string(flag));
        usleep(1);
        return;
    }
    _conn->sendInLoop(to_string(flag));
    usleep(1);
    set<int> iset=Mydict::createInstance()->getIndexTable()[word];
    if(iset.size()<5){
        string sz=to_string(iset.size());
        _conn->sendInLoop(sz);
        usleep(1);
    }else{
        _conn->sendInLoop("5");
        usleep(1);
    }
    statistic(iset);
}

string MyTask::getFirstWord()
{
    size_t idx=0;
    string key;
    char mark=_queryWord[idx];
    if(mark & 0x80)
    {
        int len=getUtf8CharLength(_queryWord[idx]);
        while(len--){
            key+=_queryWord[idx++];
        }
    }
    else{
        key+=tolower(_queryWord[idx]);
    }       
    return key;
}
int MyTask::getUtf8CharLength(char c)
{
    int len=0;
    if(c>0) return len+1;
    while(c<0){
        len++;
        c=c<<1;
    }
    return len;
}

void MyTask::statistic(set<int>& iset)
{
    for(auto &elem:iset)
    {
        string word=Mydict::createInstance()->getDict()[elem].first;
        int iFreq=Mydict::createInstance()->getDict()[elem].second;
        int iDist=distance(word);
        MyResult res(word,iFreq,iDist);
        _resultQue.push(res);
    }
}

int MyTask::distance(const string &rhs)
{
    int len1=_queryWord.size()+1;
    int len2=rhs.size()+1;
    int **dp=new int*[len1];
    for(int i=0;i!=len1;i++)
        dp[i]=new int[len2];

    for(int i=0;i!=len1;i++)
        dp[i][0]=i;
    for(int j=0;j!=len2;j++)
        dp[0][j]=j;

    for(int i=1;i!=len1;i++){
        for(int j=1;j!=len2;j++){
            int flag;
            if(_queryWord[i]==rhs[j])
                flag=0;
            else
                flag=1;

            dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+flag));
        }
    }
    return dp[len1-1][len2-1];
}

void MyTask::response()
{
    queryIndexTable();
    string msg;
    size_t sz=_resultQue.size();
    for(size_t idx=0;idx!=5&&idx!=sz;idx++)
    {
        msg=_resultQue.top()._word;
        _resultQue.pop();
        _conn->sendInLoop(msg);
        usleep(1);
    }
}
